#ifndef _LIBRARY_HPP_
#define _LIBRARY_HPP_

#include <string>
#include <iostream>
#include <sstream>

//图书的结构
typedef struct
{
    unsigned long long ISBN;
    std::string BookName;
    std::string AuthorName;
    float Price;
} Book;

class library
{
public:
    library();
    library(unsigned int library_deflect, float load_factor, unsigned int length);
    ~library();
    void input();
    const void Search_Name(std::string key);
    const void Search_ID(unsigned long long key);
    const void Print_Name();
    const void Print_ID();
    void Delete_ID(unsigned long long key);
    void Delete_Name(std::string key);

private:
    //设定图书馆的容量
    unsigned int library_deflect = 30;
    //负载系数
    float load_factor = 0.75;
    //开放定址法限定的查找范围
    unsigned int length = 20;

    unsigned int SuShu;
    const unsigned int GetSuShu();
    Book **library_no;
    Book **library_name;
    const unsigned int BKDRHash(std::string key);
    void library_up();
};

//构造
library::library()
{
    SuShu = GetSuShu();
    if (SuShu == 0)
    {
        printf("生成素数错误, 退出程序\n");
        exit(0);
    }

    library_no = new Book *[library_deflect] { nullptr };
    library_name = new Book *[library_deflect] { nullptr };
}
library::library(unsigned int library_deflect, float load_factor, unsigned int length)
{
    this->library_deflect = library_deflect;
    this->load_factor = load_factor;
    this->length = length;

    SuShu = GetSuShu();
    if (SuShu == 0)
    {
        printf("生成素数错误, 退出程序\n");
        exit(0);
    }

    library_no = new Book *[this->library_deflect];
    library_name = new Book *[this->library_deflect];
}

//析构
library::~library()
{
    for (unsigned int i = 0; i < library_deflect; i++)
        if (library_no[i] != nullptr)
            delete library_no[i];
    delete[] library_no;
    delete[] library_name;
}

const unsigned int library::GetSuShu()
{
    for (unsigned int i = library_deflect; i < (library_deflect + length); i++)
        if (i % 2 != 0 && i % 3 != 0 && i % 4 != 0)
            return i;
    return 0;
}

void library::library_up()
{
    //备份旧的图书馆
    Book **library_no_old = library_no;
    Book **library_name_old = library_name;

    //扩张图书馆容量
    library_no = new Book *[this->library_deflect * 2] { nullptr };
    library_name = new Book *[this->library_deflect * 2] { nullptr };

    //转移数据
    for (unsigned int i = 0; i < library_deflect; i++)
    {
        library_no[i] = library_no_old[i];
        library_name[i] = library_name_old[i];
    }

    //拆除旧的图书馆
    delete[] library_no_old;
    delete[] library_name_old;

    //重设图书馆容量
    library_deflect = library_deflect * 2;
}

const unsigned int library::BKDRHash(std::string key)
{
    unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
    unsigned int hash = 0;
    const char *str = key.c_str();

    while (*str)
    {
        hash = hash * seed + (*str++);
    }
    return (hash & 0x7FFFFFFF);
}

void library::input()
{
    while (1)
    {
        //接受输入
        Book *temp = new Book;
        std::string str = "";
        getline(std::cin, str);
        if (str == "")
            break;
        std::stringstream iss;
        iss.str(str);
        unsigned long long ISBN;
        std::string BookName, AuthorName;
        float Price;
        while (iss >> ISBN >> BookName >> AuthorName >> Price)
        {
            temp->ISBN = ISBN;
            temp->BookName = BookName;
            temp->AuthorName = AuthorName;
            temp->Price = Price;
        }

        //存入哈希表
        //以图书编号为索引条件
        unsigned int wan = temp->ISBN % SuShu;
        while (wan > library_deflect * load_factor)
            library_up();
        if (library_no[wan] == nullptr)
            library_no[wan] = temp;
        else
            for (wan++; wan < library_deflect; wan++)
                if (library_no[wan] == nullptr)
                {
                    library_no[wan] = temp;
                    break;
                }

        //以图书名称为索引条件
        unsigned int miao = BKDRHash(temp->BookName) % SuShu;
        while (miao > library_deflect * load_factor)
            library_up();
        if (library_name[miao] == nullptr)
            library_name[miao] = temp;
        else
            for (miao++; miao < library_deflect; miao++)
                if (library_name[miao] == nullptr)
                {
                    library_name[miao] = temp;
                    break;
                }
    }
}

const void library::Search_Name(std::string key)
{
    unsigned int miao = BKDRHash(key) % SuShu;
    unsigned int max = library_deflect;
    if (library_name[miao] != nullptr)
        if (library_name[miao]->BookName == key)
            printf("图书编号\t图书名称\t\t主编姓名\t图书价格\n%-8llu\t%-16s\t%-8s\t%.2f\n", library_name[miao]->ISBN, library_name[miao]->BookName.c_str(), library_name[miao]->AuthorName.c_str(), library_name[miao]->Price);
        else
        {
            for (miao++; miao < max; miao++)
                if (library_name[miao] != nullptr && library_name[miao]->BookName == key)
                {
                    printf("图书编号\t图书名称\t\t主编姓名\t图书价格\n%-8llu\t%-16s\t%-8s\t%.2f\n", library_name[miao]->ISBN, library_name[miao]->BookName.c_str(), library_name[miao]->AuthorName.c_str(), library_name[miao]->Price);
                    break;
                }
        }
    else
        printf("图书名称\"%s\"查找失败...请检查关键字是否正确.\n", key.c_str());
    if (miao == max)
        printf("图书名称\"%s\"查找失败...请检查关键字是否正确.\n", key.c_str());
}

const void library::Search_ID(unsigned long long key)
{
    unsigned int max = library_deflect;
    unsigned int wan = key % SuShu;
    if (library_no[wan] != nullptr)
    {
        if (library_no[wan]->ISBN == key)
            printf("图书编号\t图书名称\t\t主编姓名\t图书价格\n%-8llu\t%-16s\t%-8s\t%.2f\n", library_no[wan]->ISBN, library_no[wan]->BookName.c_str(), library_no[wan]->AuthorName.c_str(), library_no[wan]->Price);
        else
            for (wan++; wan < max; wan++)
                if (library_no[wan] != nullptr && library_no[wan]->ISBN == key)
                {
                    printf("图书编号\t图书名称\t\t主编姓名\t图书价格\n%-8llu\t%-16s\t%-8s\t%.2f\n", library_no[wan]->ISBN, library_no[wan]->BookName.c_str(), library_no[wan]->AuthorName.c_str(), library_no[wan]->Price);
                    break;
                }
    }
    else
        printf("编号\"%llu\"查找失败...请检查关键字是否正确.\n", key);
    if (wan == max)
        printf("编号\"%llu\"查找失败...请检查关键字是否正确.\n", key);
}

const void library::Print_Name()
{
    for (unsigned int i = 0; i < library_deflect; i++)
        if (library_name[i] != nullptr)
            printf("%-8llu\t%-16s\t%-8s\t%.2f\n", library_name[i]->ISBN, library_name[i]->BookName.c_str(), library_name[i]->AuthorName.c_str(), library_name[i]->Price);
}

const void library::Print_ID()
{
    for (unsigned int i = 0; i < library_deflect; i++)
        if (library_no[i] != nullptr)
            printf("%-8llu\t%-16s\t%-8s\t%.2f\n", library_no[i]->ISBN, library_no[i]->BookName.c_str(), library_no[i]->AuthorName.c_str(), library_no[i]->Price);
}

void library::Delete_ID(unsigned long long key)
{
    unsigned int max = library_deflect;
    unsigned int wan = key % SuShu;
    if (library_no[wan] != nullptr)
    {
        if (library_no[wan]->ISBN == key)
        {
            printf("图书编号\t图书名称\t\t主编姓名\t图书价格\n%-8llu\t%-16s\t%-8s\t%.2f\n", library_no[wan]->ISBN, library_no[wan]->BookName.c_str(), library_no[wan]->AuthorName.c_str(), library_no[wan]->Price);
            for (unsigned int i = 0; i < library_deflect; i++)
                if (library_name[i] == library_no[wan])
                {
                    library_name = nullptr;
                    break;
                }
            delete library_no[wan];
            library_no[wan] = nullptr;
            printf("此记录已删除\n");
        }
        else
            for (wan++; wan < max; wan++)
                if (library_no[wan] != nullptr && library_no[wan]->ISBN == key)
                {
                    printf("图书编号\t图书名称\t\t主编姓名\t图书价格\n%-8llu\t%-16s\t%-8s\t%.2f\n", library_no[wan]->ISBN, library_no[wan]->BookName.c_str(), library_no[wan]->AuthorName.c_str(), library_no[wan]->Price);
                    for (unsigned int i = 0; i < library_deflect; i++)
                        if (library_name[i] == library_no[wan])
                        {
                            library_name[i] = nullptr;
                            break;
                        }
                    delete library_no[wan];
                    library_no[wan] = nullptr;
                    printf("此记录已删除\n");
                    break;
                }
    }
    else
        printf("编号\"%llu\"查找失败...请检查关键字是否正确.\n", key);
    if (wan == max)
        printf("编号\"%llu\"查找失败...请检查关键字是否正确.\n", key);
}

void library::Delete_Name(std::string key)
{
    unsigned int miao = BKDRHash(key) % SuShu;
    unsigned int max = library_deflect;
    if (library_name[miao] != nullptr)
        if (library_name[miao]->BookName == key)
        {
            printf("图书编号\t图书名称\t\t主编姓名\t图书价格\n%-8llu\t%-16s\t%-8s\t%.2f\n", library_name[miao]->ISBN, library_name[miao]->BookName.c_str(), library_name[miao]->AuthorName.c_str(), library_name[miao]->Price);
            for (unsigned int i = 0; i < library_deflect; i++)
                if (library_no[i] == library_name[miao])
                {
                    library_no[i] = nullptr;
                    break;
                }
            delete library_name[miao];
            library_name[miao] = nullptr;
            printf("此记录已删除\n");
        }
        else
        {
            for (miao++; miao < max; miao++)
                if (library_name[miao] != nullptr && library_name[miao]->BookName == key)
                {
                    printf("图书编号\t图书名称\t\t主编姓名\t图书价格\n%-8llu\t%-16s\t%-8s\t%.2f\n", library_name[miao]->ISBN, library_name[miao]->BookName.c_str(), library_name[miao]->AuthorName.c_str(), library_name[miao]->Price);
                    for (unsigned int i = 0; i < library_deflect; i++)
                        if (library_no[i] == library_name[miao])
                        {
                            library_no[i] = nullptr;
                            break;
                        }
                    delete library_name[miao];
                    library_name[miao] = nullptr;
                    printf("此记录已删除\n");
                    break;
                }
        }
    else
        printf("图书名称\"%s\"查找失败...请检查关键字是否正确.\n", key.c_str());
    if (miao == max)
        printf("图书名称\"%s\"查找失败...请检查关键字是否正确.\n", key.c_str());
}

#endif